home *** CD-ROM | disk | FTP | other *** search
/ Graphics Plus / Graphics Plus.iso / msdos / raytrace / pov / bin / xtras / lighting.c < prev    next >
C/C++ Source or Header  |  1994-09-11  |  52KB  |  1,757 lines

  1. /****************************************************************************
  2. *
  3. *  ATTENTION!!!
  4. *
  5. *  THIS FILE HAS BEEN MODIFIED!!! IT IS NOT PART OF THE OFFICAL
  6. *  POV-RAY 2.2 DISTRIBUTION!!!
  7. *
  8. *  THIS FILE IS PART OF "FASTER THAN POV-RAY" (VERSION 2.2),
  9. *  A SPED-UP VERSION OF POV-RAY 2.2. USE AT YOUR OWN RISK!!!!!!
  10. *
  11. *  New files: addon0.c, addon1.c, addon2.c, addon3.c, addon.h
  12. *
  13. *  The additional modules were written by Dieter Bayer.
  14. *
  15. *  Send comments, suggestions, bugs, ideas ... to:
  16. *
  17. *  e-mail: dieter@cip.e-technik.uni-erlangen.de
  18. *  CIS: 100255.3074
  19. *
  20. *  All changed/added lines are enclosed in #ifdef DB_CODE ... #endif
  21. *
  22. *  The vista projection was taken from:
  23. *
  24. *    A. Hashimoto, T. Akimoto, K. Mase, and Y. Suenaga, 
  25. *    "Vista Ray-Tracing: High Speed Ray Tracing Using Perspective
  26. *    Projection Image", New Advances in Computer Graphics, Proceedings
  27. *    of CG International '89, R. A. Earnshaw, B. Wyvill (Eds.), 
  28. *    Springer, ..., pp. 549-560
  29. *
  30. *  The idea for the light buffer was taken from:
  31. *
  32. *    E. Haines and D. Greenberg, "The Light Buffer: A Shadow-Testing 
  33. *    Accelerator", IEEE CG&A, Vol. 6, No. 9, Sept. 1986, pp. 6-16
  34. *
  35. *****************************************************************************/
  36.  
  37. /****************************************************************************
  38. *                   lighting.c
  39. *
  40. *  This module calculates lighting properties like ambient, diffuse, specular,
  41. *  reflection, refraction, etc.
  42. *
  43. *  from Persistence of Vision Raytracer
  44. *  Copyright 1993 Persistence of Vision Team
  45. *---------------------------------------------------------------------------
  46. *  NOTICE: This source code file is provided so that users may experiment
  47. *  with enhancements to POV-Ray and to port the software to platforms other
  48. *  than those supported by the POV-Ray Team.  There are strict rules under
  49. *  which you are permitted to use this file.  The rules are in the file
  50. *  named POVLEGAL.DOC which should be distributed with this file. If
  51. *  POVLEGAL.DOC is not available or for more info please contact the POV-Ray
  52. *  Team Coordinator by leaving a message in CompuServe's Graphics Developer's
  53. *  Forum.  The latest version of POV-Ray may be found there as well.
  54. *
  55. * This program is based on the popular DKB raytracer version 2.12.
  56. * DKBTrace was originally written by David K. Buck.
  57. * DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins.
  58. *
  59. *****************************************************************************/
  60.  
  61. #include "frame.h"
  62. #include "vector.h"
  63. #include "povproto.h"
  64. #ifdef DB_CODE
  65. /* Changes necessary for the light buffer. */
  66. #include "addon.h"
  67. #endif
  68.  
  69. extern int Trace_Level;
  70. extern FRAME Frame;
  71. extern OBJECT *Root_Object;
  72. extern unsigned int Options;
  73. extern int Use_Slabs;
  74. extern unsigned long Quality_Flags;
  75. extern int Shadow_Test_Flag;
  76. extern long Shadow_Ray_Tests, Shadow_Rays_Succeeded, Shadow_Cache_Hits;
  77. extern long Reflected_Rays_Traced, Refracted_Rays_Traced;
  78. extern long Transmitted_Rays_Traced;
  79. #ifdef DB_CODE
  80. /* Changes necessary for the light buffer. */
  81. extern unsigned int Extended_Options;
  82. #endif
  83.  
  84. extern short *hashTable;
  85. extern unsigned short crctab[256];
  86. #define rand3d(a,b) crctab[(int)(hashTable[(int)(hashTable[(int)((a)&0xfff)]^(b))&0xfff])&0xff]
  87.  
  88. #define COORDINATE_LIMIT 1.0e17
  89. #define BLACK_LEVEL 0.003
  90.  
  91. /* "Small_Tolerance" is just too tight for higher order polynomial equations.
  92.    this value should probably be a variable of some sort, but for now just
  93.    use a reasonably small value.  If people render real small objects real
  94.    close to each other then there may be some shading problems.  Otherwise
  95.    having SHADOW_TOLERANCE as large as this won't affect images. */
  96. #define SHADOW_TOLERANCE 1.0e-3
  97.  
  98. static void do_light PARAMS((LIGHT_SOURCE *Light_Source,
  99. DBL *Light_Source_Depth, RAY *Light_Source_Ray, VECTOR *IPoint,
  100. COLOUR *Light_Colour));
  101. static int do_blocking PARAMS((INTERSECTION *Local_Intersection,
  102. COLOUR *Light_Colour, ISTACK *Local_Stack));
  103. static void do_phong PARAMS((FINISH *Finish, RAY *Light_Source_Ray,
  104. VECTOR *Eye, VECTOR *Layer_Normal, COLOUR *Colour, COLOUR *Light_Colour,
  105. COLOUR *Layer_Pigment_Colour));
  106. static void do_specular PARAMS((FINISH *Finish, RAY *Light_Source_Ray,
  107. VECTOR *REye, VECTOR *Layer_Normal, COLOUR *Colour, COLOUR *Light_Colour,
  108. COLOUR *Layer_Pigment_Colour));
  109. static void do_diffuse PARAMS((FINISH *Finish, RAY *Light_Source_Ray,
  110. VECTOR *Layer_Normal, COLOUR *Colour, COLOUR *Light_Colour,
  111. COLOUR *Layer_Pigment_Colour, DBL Attenuation));
  112. static void Block_Area_Light PARAMS((LIGHT_SOURCE *Light_Source,
  113. DBL Light_Source_Depth, RAY *Light_Source_Ray_Ptr, VECTOR *IPoint,
  114. COLOUR *Light_Colour, int u1, int v1, int u2, int v2, int Level));
  115. static void Block_Point_Light PARAMS((LIGHT_SOURCE *Light_Source,
  116. DBL Light_Source_Depth, RAY *Light_Source_Ray_Ptr, COLOUR *Light_Colour));
  117.  
  118. #ifdef DB_CODE
  119. /* Changes necessary for the light buffer. */
  120. static void Block_Point_Light_Light_Buffer PARAMS((LIGHT_SOURCE *Light_Source,
  121.   DBL Light_Source_Depth, RAY *Light_Source_Ray_Ptr, COLOUR *Light_Colour));
  122.  
  123.  
  124.  
  125. /******************************************************************************
  126.    Intersect a shadow ray with the light buffer tree.
  127.  ******************************************************************************/
  128. static void Block_Point_Light_Light_Buffer (Light_Source, Light_Source_Depth, Light_Source_Ray_Ptr, Light_Colour)
  129. LIGHT_SOURCE *Light_Source;
  130. DBL Light_Source_Depth;
  131. RAY *Light_Source_Ray_Ptr;
  132. COLOUR *Light_Colour;
  133. {
  134.   int Quit_Looking, Not_Found_Shadow, Cache_Me;
  135.   ISTACK *Local_Stack;
  136.   RAY Light_Source_Ray;
  137.   INTERSECTION *Local_Intersection, Bounded_Intersection;
  138.   RAY Local_Ray;
  139.  
  140.   VECTOR V;
  141.   DBL ax, ay, az;
  142.   int u, v, axis;
  143.   OBJECT *Blocking_Object;
  144.  
  145.   Light_Source_Ray = *Light_Source_Ray_Ptr;
  146.  
  147.   Local_Stack = open_istack ();
  148.   Quit_Looking = FALSE;
  149.  
  150.   /* Test the cached object first */
  151.   /* Made changes so that semi-transparent objects never get cached */
  152.  
  153.   if (Light_Source->Shadow_Cached_Object != NULL)
  154.   {
  155.     Shadow_Ray_Tests++;
  156.  
  157.     if (Ray_In_Bounds(&Light_Source_Ray, Light_Source->Shadow_Cached_Object->Bound))
  158.     {
  159.       if (All_Intersections(Light_Source->Shadow_Cached_Object, &Light_Source_Ray, Local_Stack))
  160.       {
  161.     while ((Local_Intersection=pop_entry(Local_Stack)) != NULL)
  162.     {
  163.       if ((!Local_Intersection->Object->No_Shadow_Flag) &&
  164.           (Local_Intersection->Depth < Light_Source_Depth-Small_Tolerance) &&
  165.           (Local_Intersection->Depth > SHADOW_TOLERANCE))
  166.       {
  167.         if (do_blocking(Local_Intersection, Light_Colour, Local_Stack))
  168.         {
  169.           Quit_Looking = TRUE;
  170.           Shadow_Cache_Hits++;
  171.           break;
  172.         }
  173.       }
  174.     }
  175.       }
  176.     }
  177.   }
  178.  
  179.   if (Quit_Looking)
  180.   {
  181.     close_istack(Local_Stack);
  182.     return;
  183.   }
  184.  
  185.   V.x = -Light_Source_Ray.Direction.x;
  186.   V.y = -Light_Source_Ray.Direction.y;
  187.   V.z = -Light_Source_Ray.Direction.z;
  188.  
  189.   ax = fabs(V.x);
  190.   ay = fabs(V.y);
  191.   az = fabs(V.z);
  192.  
  193.   if ((ax>ay) && (ax>az))
  194.   {
  195.     if (V.x>0.0)
  196.       axis = XaxisP;
  197.     else
  198.       axis = XaxisM;
  199.     u = (int)(MAX_LB_ENTRY * V.y/ax);
  200.     v = (int)(MAX_LB_ENTRY * V.z/ax);
  201.   }
  202.   else
  203.   {
  204.     if (ay>az)
  205.     {
  206.       if (V.y>0.0)
  207.     axis = YaxisP;
  208.       else
  209.     axis = YaxisM;
  210.       u = (int)(MAX_LB_ENTRY * V.x/ay);
  211.       v = (int)(MAX_LB_ENTRY * V.z/ay);
  212.     }
  213.     else
  214.     {
  215.       if (V.z>0.0)
  216.     axis = ZaxisP;
  217.       else
  218.     axis = ZaxisM;
  219.       u = (int)(MAX_LB_ENTRY * V.x/az);
  220.       v = (int)(MAX_LB_ENTRY * V.y/az);
  221.     }
  222.   }
  223.  
  224.   if (Light_Source->Light_Buffer[axis] == NULL)
  225.   {
  226.     close_istack(Local_Stack);
  227.     return;
  228.   }
  229.  
  230.   Not_Found_Shadow = TRUE;
  231.   Cache_Me = FALSE;
  232.  
  233.   Local_Ray = Light_Source_Ray;
  234.  
  235.   while (!Quit_Looking)
  236.   {
  237.     Shadow_Ray_Tests++;
  238.  
  239.     Local_Ray.Quadric_Constants_Cached = 0;
  240.  
  241.     Bounded_Intersection.Depth = Light_Source_Depth;
  242.  
  243.     if (Intersect_Light_Tree(&Local_Ray, Light_Source->Light_Buffer[axis],
  244.     u, v, &Bounded_Intersection, &Blocking_Object))
  245.     {
  246.       if (Bounded_Intersection.Depth > Light_Source_Depth)
  247.     break; /* Intersection was beyond the light */
  248.  
  249.       if (!(Bounded_Intersection.Object->No_Shadow_Flag))
  250.       {
  251.     if (Blocking_Object != Light_Source->Shadow_Cached_Object)
  252.     {
  253.       Shadow_Rays_Succeeded++;
  254.  
  255.       Filter_Shadow_Ray(&Bounded_Intersection, Light_Colour);
  256.  
  257.       if ((fabs(Light_Colour->Red) < BLACK_LEVEL) &&
  258.           (fabs(Light_Colour->Green) < BLACK_LEVEL) &&
  259.           (fabs(Light_Colour->Blue) < BLACK_LEVEL))
  260.       {
  261.         Cache_Me = Not_Found_Shadow;
  262.         Quit_Looking = TRUE;
  263.         break; /* from while */
  264.       }
  265.     }
  266.       }
  267.  
  268.       /* Move the ray to the point of intersection, plus some */
  269.  
  270.       Light_Source_Depth -= Bounded_Intersection.Depth;
  271.  
  272.       Local_Ray.Initial = Bounded_Intersection.IPoint;
  273.  
  274.       Not_Found_Shadow = FALSE;
  275.     }
  276.     else /* No intersections in the direction of the ray */
  277.     {
  278.       break;
  279.     }
  280.   } /*endwhile*/
  281.  
  282.   if (Cache_Me)
  283.   {
  284.     Light_Source->Shadow_Cached_Object = Blocking_Object;
  285.   }
  286.  
  287.   close_istack(Local_Stack);
  288. }
  289. #endif
  290.  
  291. static void Block_Point_Light (Light_Source, Light_Source_Depth, Light_Source_Ray_Ptr, Light_Colour)
  292. LIGHT_SOURCE *Light_Source;
  293. DBL Light_Source_Depth;
  294. RAY *Light_Source_Ray_Ptr;
  295. COLOUR *Light_Colour;
  296.   {
  297.   OBJECT *Blocking_Object;
  298.   int Quit_Looking, Not_Found_Shadow, Cache_Me;
  299.   INTERSECTION *Local_Intersection, Bounded_Intersection;
  300.   ISTACK *Local_Stack;
  301.   RAY Local_Ray;
  302.   RAY Light_Source_Ray;
  303.  
  304.   Light_Source_Ray = *Light_Source_Ray_Ptr;
  305.  
  306.   Local_Stack = open_istack ();
  307.   Quit_Looking = FALSE;
  308.  
  309.   /* Test the cached object first */
  310.   /* Made changes so that semi-transparent objects never get cached */
  311.   if (Light_Source->Shadow_Cached_Object != NULL) 
  312.     {
  313.     Shadow_Ray_Tests++;
  314.  
  315.     if (Ray_In_Bounds (&Light_Source_Ray, Light_Source->Shadow_Cached_Object->Bound))
  316.       {
  317.       if (All_Intersections (Light_Source->Shadow_Cached_Object, &Light_Source_Ray, Local_Stack))
  318.         while ((Local_Intersection=pop_entry(Local_Stack)) != NULL)
  319.       {
  320.           if ((!Local_Intersection->Object->No_Shadow_Flag) && 
  321.         (Local_Intersection->Depth < Light_Source_Depth-Small_Tolerance) &&
  322.             (Local_Intersection->Depth > SHADOW_TOLERANCE))
  323.             if (do_blocking(Local_Intersection, Light_Colour, Local_Stack))
  324.           {
  325.               Quit_Looking = TRUE;
  326.               Shadow_Cache_Hits++;
  327.               break;
  328.               }
  329.           }
  330.       }
  331.     }
  332.  
  333.   if (Quit_Looking) 
  334.     {
  335.     close_istack (Local_Stack);
  336.     return;
  337.     }
  338.  
  339.   Not_Found_Shadow = TRUE;   
  340.   Cache_Me = FALSE;
  341.   if (!Use_Slabs)
  342.     {
  343.     for (Blocking_Object = Frame.Objects;
  344.     Blocking_Object != NULL;
  345.     Blocking_Object = Blocking_Object->Sibling)
  346.       {
  347.       if (Blocking_Object == Light_Source->Shadow_Cached_Object)
  348.     continue;
  349.  
  350.       Shadow_Ray_Tests++;
  351.  
  352.       if (!Ray_In_Bounds (&Light_Source_Ray, Blocking_Object->Bound))
  353.     continue;
  354.  
  355.       if (!All_Intersections (Blocking_Object, &Light_Source_Ray, Local_Stack))
  356.     continue;
  357.  
  358.       while ((Local_Intersection = pop_entry(Local_Stack)) != NULL)
  359.     if ((!Local_Intersection->Object->No_Shadow_Flag) &&
  360.           (Local_Intersection->Depth < Light_Source_Depth-Small_Tolerance) && 
  361.           (Local_Intersection->Depth > SHADOW_TOLERANCE))
  362.           {
  363.           if (do_blocking(Local_Intersection, Light_Colour, Local_Stack))
  364.             {
  365.             Cache_Me = Not_Found_Shadow;
  366.             Quit_Looking = TRUE;
  367.             break; /* from while */
  368.             }
  369.           Not_Found_Shadow = FALSE;
  370.       }
  371.       if (Quit_Looking)
  372.     break; /* from for */
  373.       }
  374.     }
  375.   else   /* Use bounding slabs to look for shadows */
  376.     {
  377.     Local_Ray = Light_Source_Ray;
  378.     while (!Quit_Looking)
  379.       {
  380.       Shadow_Ray_Tests++;
  381.       Local_Ray.Quadric_Constants_Cached = 0;
  382.       Bounded_Intersection.Depth = Light_Source_Depth;
  383.       if (Bounds_Intersect(Root_Object, &Local_Ray, &Bounded_Intersection,
  384.     &Blocking_Object))
  385.     {
  386.     if (Bounded_Intersection.Depth > Light_Source_Depth)
  387.       break; /* Intersection was beyond the light */
  388.  
  389.     if (!(Bounded_Intersection.Object->No_Shadow_Flag))
  390.       if (Blocking_Object != Light_Source->Shadow_Cached_Object)
  391.         {
  392.         Shadow_Rays_Succeeded++;
  393.         Filter_Shadow_Ray(&Bounded_Intersection, Light_Colour);
  394.         if ((fabs(Light_Colour->Red) < BLACK_LEVEL) &&
  395.           (fabs(Light_Colour->Green) < BLACK_LEVEL) &&
  396.           (fabs(Light_Colour->Blue) < BLACK_LEVEL))
  397.           {
  398.           Cache_Me = Not_Found_Shadow;
  399.           Quit_Looking = TRUE;
  400.           break; /* from while */
  401.           }
  402.         }
  403.     /* Move the ray to the point of intersection, plus some */
  404.     Light_Source_Depth -= Bounded_Intersection.Depth;
  405.     Local_Ray.Initial = Bounded_Intersection.IPoint;
  406.     Not_Found_Shadow = FALSE;
  407.     }
  408.       else /* No intersections in the direction of the ray */
  409.     {
  410.     break;
  411.     }
  412.       } /*endwhile*/
  413.     } /*endelse*/
  414.   if (Cache_Me) 
  415.     Light_Source->Shadow_Cached_Object = Blocking_Object;
  416.   close_istack (Local_Stack);
  417.   }
  418.  
  419.  
  420. static void Block_Area_Light (Light_Source, Light_Source_Depth,
  421. Light_Source_Ray_Ptr,IPoint, Light_Colour, u1, v1, u2, v2, Level)
  422. LIGHT_SOURCE *Light_Source;
  423. DBL Light_Source_Depth;
  424. RAY *Light_Source_Ray_Ptr;
  425. VECTOR *IPoint;
  426. COLOUR *Light_Colour;
  427. int u1, v1, u2, v2, Level;
  428.   {
  429.   COLOUR Sample_Colour[4], Dummy_Colour;
  430.   VECTOR Center_Save, NewAxis1, NewAxis2;
  431.   int i, j, u, v, New_u1, New_v1, New_u2, New_v2;
  432.  
  433.   DBL Jitter_u, Jitter_v, ScaleFactor;
  434.   RAY Light_Source_Ray;
  435.  
  436.   Light_Source_Ray = *Light_Source_Ray_Ptr;
  437.  
  438.   /* First call, initialize */
  439.   if (u1 == 0 && v1 == 0 && u2 == 0 && v2 == 0) 
  440.     {
  441.     /* Flag uncalculated points with a negative value for Red */
  442.     for (i = 0; i < Light_Source->Area_Size1; i++) 
  443.       {
  444.       for (j = 0; j < Light_Source->Area_Size2; j++)
  445.         Light_Source->Light_Grid[i][j].Red = -1.0;
  446.       }
  447.  
  448.     u1 = 0;
  449.     v1 = 0;
  450.     u2 = Light_Source->Area_Size1 - 1;
  451.     v2 = Light_Source->Area_Size2 - 1;
  452.     }
  453.  
  454.   /* Save the light source center since we'll be fiddling with it */
  455.   Center_Save=Light_Source->Center;
  456.  
  457.   /* Sample the four corners of the region */
  458.   for (i = 0; i < 4; i++) 
  459.     {
  460.     switch (i) 
  461.     {
  462.     case 0: 
  463.       u = u1; v = v1; break;
  464.     case 1: 
  465.       u = u2; v = v1; break;
  466.     case 2: 
  467.       u = u1; v = v2; break;
  468.     case 3: 
  469.       u = u2; v = v2; break;
  470.     }
  471.  
  472.     if (Light_Source -> Light_Grid[u][v].Red >= 0.0)
  473.       /* We've already calculated this point, reuse it */
  474.       Sample_Colour[i]=Light_Source->Light_Grid[u][v];
  475.     else
  476.       {
  477.       Jitter_u = (DBL)u;
  478.       Jitter_v = (DBL)v;
  479.  
  480.       if (Light_Source -> Jitter) 
  481.         {
  482.         Jitter_u += (rand() % 4096)/4096.0 - 0.5;
  483.         Jitter_v += (rand() % 4096)/4096.0 - 0.5;
  484.         /*
  485.   Not sure if    jx = IPoint->x + 100*u;
  486.   this works    jy = IPoint->y + 100*v;
  487.   yet
  488.         Jitter_u += ((rand3d(jx, jy) & 0x7FFF)/32768.0) - 0.5;
  489.         Jitter_v += ((rand3d(jx+10, jy+10) & 0x7FFF)/32768.0) - 0.5;
  490. */
  491.         }
  492.  
  493.       if (Light_Source -> Area_Size1 > 1) 
  494.         {
  495.         ScaleFactor = Jitter_u/(DBL)(Light_Source->Area_Size1 - 1) - 0.5;
  496.         VScale (NewAxis1, Light_Source->Axis1, ScaleFactor)
  497.           }
  498.       else
  499.         Make_Vector (&NewAxis1, 0.0, 0.0, 0.0);
  500.  
  501.       if (Light_Source -> Area_Size2 > 1) 
  502.         {
  503.         ScaleFactor = Jitter_v/(DBL)(Light_Source->Area_Size2 - 1) - 0.5;
  504.         VScale (NewAxis2, Light_Source->Axis2, ScaleFactor)
  505.         }
  506.       else
  507.         Make_Vector (&NewAxis2, 0.0, 0.0, 0.0);
  508.  
  509.       Light_Source->Center=Center_Save;
  510.       VAdd  (Light_Source->Center, Light_Source->Center, NewAxis1);
  511.       VAdd  (Light_Source->Center, Light_Source->Center, NewAxis2);
  512.  
  513.       /* Recalculate the light source ray but not the colour */
  514.       do_light (Light_Source, &Light_Source_Depth, &Light_Source_Ray,
  515.         IPoint, &Dummy_Colour);
  516.  
  517.       Sample_Colour[i]= *Light_Colour;
  518.  
  519.       Block_Point_Light (Light_Source, Light_Source_Depth,
  520.         &Light_Source_Ray, &Sample_Colour[i]);
  521.  
  522.       Light_Source->Light_Grid[u][v]=Sample_Colour[i];
  523.       }
  524.     }
  525.  
  526.   Light_Source->Center=Center_Save;
  527.  
  528.   if ( (u2 - u1 > 1 || v2 - v1 > 1) && (Level < Light_Source -> Adaptive_Level ||
  529.     Colour_Distance (&Sample_Colour[0], &Sample_Colour[1]) > 0.1 ||
  530.     Colour_Distance (&Sample_Colour[1], &Sample_Colour[3]) > 0.1 ||
  531.     Colour_Distance (&Sample_Colour[3], &Sample_Colour[2]) > 0.1 ||
  532.     Colour_Distance (&Sample_Colour[2], &Sample_Colour[0]) > 0.1) )
  533.     {
  534.     for (i = 0; i < 4; i++) 
  535.       {
  536.       switch (i) 
  537.       {
  538.       case 0: 
  539.         New_u1 = u1;
  540.         New_v1 = v1;
  541.         New_u2 = (int)floor ((u1 + u2)/2.0);
  542.         New_v2 = (int)floor ((v1 + v2)/2.0);
  543.         break;
  544.  
  545.       case 1: 
  546.         New_u1 = (int)ceil  ((u1 + u2)/2.0);
  547.         New_v1 = v1;
  548.         New_u2 = u2;
  549.         New_v2 = (int)floor ((v1 + v2)/2.0);
  550.         break;
  551.  
  552.       case 2: 
  553.         New_u1 = u1;
  554.         New_v1 = (int)ceil  ((v1 + v2)/2.0);
  555.         New_u2 = (int)floor ((u1 + u2)/2.0);
  556.         New_v2 = v2;
  557.         break;
  558.  
  559.       case 3: 
  560.         New_u1 = (int)ceil ((u1 + u2)/2.0);
  561.         New_v1 = (int)ceil ((v1 + v2)/2.0);
  562.         New_u2 = u2;
  563.         New_v2 = v2;
  564.         break;
  565.       }
  566.  
  567.       /* Recalculate the light source ray but not the colour */
  568.       do_light (Light_Source, &Light_Source_Depth, &Light_Source_Ray,
  569.         IPoint, &Dummy_Colour);
  570.  
  571.       Sample_Colour[i]= *Light_Colour;
  572.  
  573.       Block_Area_Light (Light_Source, Light_Source_Depth,
  574.         &Light_Source_Ray, IPoint,
  575.         &Sample_Colour[i],
  576.         New_u1, New_v1, New_u2, New_v2, Level+1);
  577.       }
  578.     }
  579.  
  580.   /* Add up the light contributions */
  581.   Make_Colour (Light_Colour, 0.0, 0.0, 0.0);
  582.  
  583.   for (i = 0; i < 4; i++) 
  584.     {
  585.     Scale_Colour (&Sample_Colour[i], &Sample_Colour[i], 0.25);
  586.     Add_Colour (Light_Colour, Light_Colour, &Sample_Colour[i]);
  587.     }
  588.   }
  589.  
  590. static void do_light(Light_Source, Light_Source_Depth, Light_Source_Ray, IPoint, Light_Colour)
  591. LIGHT_SOURCE *Light_Source;
  592. DBL *Light_Source_Depth;
  593. RAY *Light_Source_Ray;
  594. VECTOR *IPoint;
  595. COLOUR *Light_Colour;
  596.   {
  597.   DBL Attenuation = 1.0;
  598.  
  599.   /* Get the light source colour. */
  600.   *Light_Colour = Light_Source->Colour;
  601.  
  602.   Light_Source_Ray->Initial = *IPoint;
  603.   Light_Source_Ray->Quadric_Constants_Cached = FALSE;
  604.  
  605.   VSub (Light_Source_Ray->Direction,
  606.     Light_Source->Center,
  607.     *IPoint);
  608.  
  609.   VLength (*Light_Source_Depth, Light_Source_Ray->Direction);
  610.  
  611.   VScale (Light_Source_Ray->Direction, Light_Source_Ray->Direction,
  612.     1.0/(*Light_Source_Depth));
  613.  
  614.   Attenuation = Attenuate_Light(Light_Source, Light_Source_Ray);
  615.  
  616.   /* Now scale the color by the attenuation */
  617.   Light_Colour->Red   *= Attenuation;
  618.   Light_Colour->Green *= Attenuation;
  619.   Light_Colour->Blue  *= Attenuation;
  620.  
  621.  
  622.   return;
  623.   }
  624.  
  625. static int do_blocking(Local_Intersection, Light_Colour, Local_Stack)
  626. INTERSECTION *Local_Intersection;
  627. COLOUR *Light_Colour;
  628. ISTACK *Local_Stack;
  629.   {
  630.   Shadow_Rays_Succeeded++;
  631.  
  632.   Filter_Shadow_Ray (Local_Intersection, Light_Colour);
  633.  
  634.   if ((fabs(Light_Colour->Red) < BLACK_LEVEL) && 
  635.     (fabs(Light_Colour->Green) < BLACK_LEVEL) && 
  636.     (fabs(Light_Colour->Blue) < BLACK_LEVEL)) 
  637.     {
  638.     while ((Local_Intersection = pop_entry(Local_Stack)) != NULL)
  639.       {
  640.       }
  641.     return(TRUE);
  642.     }
  643.   return(FALSE);
  644.   }
  645.  
  646. #ifdef DB_CODE
  647. /* Some things have been optimized. */
  648. /******************************************************************************
  649.    Light_Source_Ray->Direction is a unit vector, so its length       
  650.    needn't be calculated!                                            
  651.    
  652.    The first test (Cos_Angle_Of_Incidence < 0.0) is unnecessary,     
  653.    since the negation of Normal_Component leads to the same result     
  654.    as the negation of the normal vector!                             
  655.  ******************************************************************************/
  656. static void do_phong(Finish, Light_Source_Ray, Eye, Layer_Normal, Colour, Light_Colour, Layer_Pigment_Colour)
  657. FINISH *Finish;
  658. RAY *Light_Source_Ray;
  659. VECTOR *Layer_Normal, *Eye;
  660. COLOUR *Colour, *Light_Colour, *Layer_Pigment_Colour;
  661. {
  662.   DBL k; /* Cos_Angle_Of_Incidence */
  663.   DBL Intensity;
  664.   VECTOR Reflect_Direction;
  665.  
  666.   k = 2.0 * (Eye->x * Layer_Normal->x +
  667.          Eye->y * Layer_Normal->y +
  668.          Eye->z * Layer_Normal->z);
  669.  
  670.   Reflect_Direction.x = Eye->x - k * Layer_Normal->x;
  671.   Reflect_Direction.y = Eye->y - k * Layer_Normal->y;
  672.   Reflect_Direction.z = Eye->z - k * Layer_Normal->z;
  673.  
  674.   VDot (k, Reflect_Direction, Light_Source_Ray->Direction);
  675.  
  676.   if (k <= 0.0)
  677.     return;
  678.  
  679.   if (Finish->Phong_Size != 1.0)
  680.     Intensity = Finish->Phong * pow(k, Finish->Phong_Size);
  681.   else
  682.     Intensity = Finish->Phong * k;
  683.  
  684.   if (Finish->Metallic_Flag)
  685.   {
  686.     Colour->Red+=Intensity*(Layer_Pigment_Colour->Red)*(Light_Colour->Red);
  687.     Colour->Green+=Intensity*(Layer_Pigment_Colour->Green)*(Light_Colour->Green);
  688.     Colour->Blue+=Intensity*(Layer_Pigment_Colour->Blue)*(Light_Colour->Blue);
  689.   }
  690.   else
  691.   {
  692.     Colour->Red+=Intensity*(Light_Colour->Red);
  693.     Colour->Green+=Intensity*(Light_Colour->Green);
  694.     Colour->Blue+=Intensity*(Light_Colour->Blue);
  695.   }
  696. }
  697. #else
  698. static void do_phong(Finish, Light_Source_Ray, Eye, Layer_Normal, Colour, Light_Colour, Layer_Pigment_Colour)
  699. FINISH *Finish;
  700. RAY *Light_Source_Ray;
  701. VECTOR *Layer_Normal, *Eye;
  702. COLOUR *Colour, *Light_Colour, *Layer_Pigment_Colour;
  703.   {
  704.   DBL Cos_Angle_Of_Incidence, Normal_Length, Intensity;
  705.   VECTOR Local_Normal, Normal_Projection, Reflect_Direction;
  706.  
  707.   VDot(Cos_Angle_Of_Incidence, *Eye, *Layer_Normal);
  708.  
  709.   if (Cos_Angle_Of_Incidence < 0.0)
  710.     {
  711.     Local_Normal = *Layer_Normal;
  712.     Cos_Angle_Of_Incidence = -Cos_Angle_Of_Incidence;
  713.     }
  714.   else
  715.     {
  716.     VScale (Local_Normal, *Layer_Normal, -1.0);
  717.     }
  718.  
  719.   VScale (Normal_Projection, Local_Normal, Cos_Angle_Of_Incidence);
  720.   VScale (Normal_Projection, Normal_Projection, 2.0);
  721.   VAdd (Reflect_Direction, *Eye, Normal_Projection);
  722.  
  723.   VDot (Cos_Angle_Of_Incidence, Reflect_Direction, Light_Source_Ray->Direction);
  724.   VLength (Normal_Length, Light_Source_Ray->Direction);
  725.  
  726.   if (Normal_Length == 0.0)
  727.     Cos_Angle_Of_Incidence = 0.0;
  728.   else 
  729.     Cos_Angle_Of_Incidence /= Normal_Length;
  730.  
  731.   if (Cos_Angle_Of_Incidence < 0.0)
  732.     Cos_Angle_Of_Incidence = 0;
  733.  
  734.   if (Finish->Phong_Size != 1.0)
  735.     Intensity = pow(Cos_Angle_Of_Incidence, Finish->Phong_Size);
  736.   else
  737.     Intensity = Cos_Angle_Of_Incidence;
  738.  
  739.   Intensity *= Finish->Phong;
  740.  
  741.   if (Finish->Metallic_Flag) 
  742.     {
  743.     Colour->Red+=Intensity*(Layer_Pigment_Colour->Red)*(Light_Colour->Red);    
  744.     Colour->Green+=Intensity*(Layer_Pigment_Colour->Green)*(Light_Colour->Green);
  745.     Colour->Blue+=Intensity*(Layer_Pigment_Colour->Blue)*(Light_Colour->Blue);  
  746.     }
  747.   else 
  748.     {
  749.     Colour->Red+=Intensity*(Light_Colour->Red);
  750.     Colour->Green+=Intensity*(Light_Colour->Green);
  751.     Colour->Blue+=Intensity*(Light_Colour->Blue);  
  752.     }
  753.   }
  754. #endif
  755.  
  756. #ifdef DB_CODE
  757. /* Some things have been optimized. */
  758. /******************************************************************************
  759.    There's no need to multiply the vector Halfway by 0.5!            
  760.    The normal vector is already unit!                                
  761.  ******************************************************************************/
  762. static void do_specular(Finish, Light_Source_Ray, REye, Layer_Normal, Colour, Light_Colour, Layer_Pigment_Colour)
  763. FINISH *Finish;
  764. RAY *Light_Source_Ray;
  765. VECTOR *Layer_Normal, *REye;
  766. COLOUR *Colour, *Light_Colour, *Layer_Pigment_Colour;
  767. {
  768.   DBL Cos_Angle_Of_Incidence, Intensity, Halfway_Length;
  769.   VECTOR Halfway;
  770.  
  771.   Halfway.x = REye->x + Light_Source_Ray->Direction.x;
  772.   Halfway.y = REye->y + Light_Source_Ray->Direction.y;
  773.   Halfway.z = REye->z + Light_Source_Ray->Direction.z;
  774.  
  775.   VLength (Halfway_Length, Halfway);
  776.  
  777.   VDot (Cos_Angle_Of_Incidence, Halfway, *Layer_Normal);
  778.  
  779.   if (Cos_Angle_Of_Incidence <= 0.0)
  780.     return;
  781.   else
  782.     Cos_Angle_Of_Incidence /= Halfway_Length;
  783.  
  784.   if (Finish->Roughness != 1.0)
  785.     Intensity = Finish->Specular * pow(Cos_Angle_Of_Incidence, Finish->Roughness);
  786.   else
  787.     Intensity = Finish->Specular * Cos_Angle_Of_Incidence;
  788.  
  789.   if (Finish->Metallic_Flag)
  790.   {
  791.     Colour->Red+=Intensity*(Layer_Pigment_Colour->Red)*(Light_Colour->Red);
  792.     Colour->Green+=Intensity*(Layer_Pigment_Colour->Green)*(Light_Colour->Green);
  793.     Colour->Blue+=Intensity*(Layer_Pigment_Colour->Blue)*(Light_Colour->Blue);
  794.   }
  795.   else
  796.   {
  797.     Colour->Red+=Intensity*(Light_Colour->Red);
  798.     Colour->Green+=Intensity*(Light_Colour->Green);
  799.     Colour->Blue+=Intensity*(Light_Colour->Blue);
  800.   }
  801. }
  802. #else
  803. static void do_specular(Finish, Light_Source_Ray, REye, Layer_Normal, Colour, Light_Colour, Layer_Pigment_Colour)
  804. FINISH *Finish;
  805. RAY *Light_Source_Ray;
  806. VECTOR *Layer_Normal, *REye;
  807. COLOUR *Colour, *Light_Colour, *Layer_Pigment_Colour;
  808.   {
  809.   DBL Cos_Angle_Of_Incidence, Normal_Length, Intensity, Halfway_Length;
  810.   VECTOR Halfway;
  811.  
  812.   VHalf (Halfway, *REye, Light_Source_Ray->Direction);
  813.   VLength (Normal_Length, *Layer_Normal);
  814.   VLength (Halfway_Length, Halfway);
  815.   VDot (Cos_Angle_Of_Incidence, Halfway, *Layer_Normal);
  816.  
  817.   if (Normal_Length == 0.0 || Halfway_Length == 0.0)
  818.     Cos_Angle_Of_Incidence = 0.0;
  819.   else
  820.     Cos_Angle_Of_Incidence /= (Normal_Length * Halfway_Length);
  821.  
  822.   if (Cos_Angle_Of_Incidence < 0.0)
  823.     Cos_Angle_Of_Incidence = 0.0;
  824.  
  825.  
  826.   if (Finish->Roughness != 1.0)
  827.     Intensity = pow(Cos_Angle_Of_Incidence, Finish->Roughness);
  828.   else
  829.     Intensity = Cos_Angle_Of_Incidence;
  830.  
  831.   Intensity *= Finish->Specular;
  832.   if (Finish->Metallic_Flag) 
  833.     {
  834.     Colour->Red+=Intensity*(Layer_Pigment_Colour->Red)*(Light_Colour->Red);    
  835.     Colour->Green+=Intensity*(Layer_Pigment_Colour->Green)*(Light_Colour->Green);
  836.     Colour->Blue+=Intensity*(Layer_Pigment_Colour->Blue)*(Light_Colour->Blue);  
  837.     }
  838.   else 
  839.     {
  840.     Colour->Red+=Intensity*(Light_Colour->Red);
  841.     Colour->Green+=Intensity*(Light_Colour->Green);
  842.     Colour->Blue+=Intensity*(Light_Colour->Blue);
  843.     }
  844.   }
  845. #endif
  846.  
  847. static void do_diffuse(Finish, Light_Source_Ray, Layer_Normal, Colour, Light_Colour, Layer_Pigment_Colour, Attenuation)
  848. FINISH *Finish;
  849. RAY *Light_Source_Ray;
  850. VECTOR *Layer_Normal;
  851. COLOUR *Colour, *Light_Colour, *Layer_Pigment_Colour;
  852. DBL Attenuation;
  853.   {
  854.   DBL Cos_Angle_Of_Incidence, Intensity;
  855.  
  856.   VDot (Cos_Angle_Of_Incidence, *Layer_Normal, Light_Source_Ray->Direction);
  857.   if (Cos_Angle_Of_Incidence < 0.0)
  858.     Cos_Angle_Of_Incidence = -Cos_Angle_Of_Incidence;
  859.  
  860.   if (Finish->Brilliance != 1.0)
  861.     Intensity = pow(Cos_Angle_Of_Incidence, Finish->Brilliance);
  862.   else
  863.     Intensity = Cos_Angle_Of_Incidence;
  864.  
  865.   Intensity *= Finish->Diffuse * Attenuation;
  866.  
  867.   if (Finish->Crand > 0.0)
  868.     Intensity -= ((rand()&0x7FFF)/(DBL) 0x7FFF) * Finish->Crand;
  869.  
  870.   Colour->Red += Intensity * (Layer_Pigment_Colour->Red) * (Light_Colour->Red);
  871.   Colour->Green += Intensity * (Layer_Pigment_Colour->Green) * (Light_Colour->Green);
  872.   Colour->Blue += Intensity * (Layer_Pigment_Colour->Blue) * (Light_Colour->Blue);
  873.   return;
  874.   }
  875.  
  876. /* Given a 3d point and a pigment, accumulate colour from that layer */
  877. /* Formerly called "Colour_At" */
  878. void Add_Pigment (Colour, Pigment, IPoint)
  879. COLOUR *Colour;
  880. PIGMENT *Pigment;
  881. VECTOR *IPoint;
  882.   {
  883.   register DBL x, y, z;
  884.   VECTOR TPoint,PTurbulence;
  885.  
  886.   if (Pigment->Trans != NULL) 
  887.     MInvTransPoint (&TPoint, IPoint, Pigment->Trans);
  888.   else 
  889.     TPoint = *IPoint;
  890.  
  891.   x = TPoint.x;
  892.   y = TPoint.y;
  893.   z = TPoint.z;
  894.   if(Pigment->Type != WOOD_PIGMENT &&
  895.     Pigment->Type != MARBLE_PIGMENT &&
  896.     Pigment->Type != NO_PIGMENT &&
  897.     Pigment->Type != COLOUR_PIGMENT &&
  898.     /*      Pigment->Type != SPOTTED_PIGMENT && */ /*maybe?*/
  899.     Pigment->Flags & HAS_TURB)
  900.     {
  901.     DTurbulence (&PTurbulence, x, y, z,
  902.       Pigment->omega,Pigment->lambda,Pigment->Octaves);
  903.     x += PTurbulence.x * Pigment->Turbulence.x;
  904.     y += PTurbulence.y * Pigment->Turbulence.y;
  905.     z += PTurbulence.z * Pigment->Turbulence.z;
  906.     }
  907.  
  908.  
  909.   if (x > COORDINATE_LIMIT)
  910.     x = COORDINATE_LIMIT;
  911.   else
  912.     if (x < -COORDINATE_LIMIT)
  913.       x = -COORDINATE_LIMIT;
  914.  
  915.   if (y > COORDINATE_LIMIT)
  916.     y = COORDINATE_LIMIT;
  917.   else
  918.     if (y < -COORDINATE_LIMIT)
  919.       y = -COORDINATE_LIMIT;
  920.  
  921.   if (z > COORDINATE_LIMIT)
  922.     z = COORDINATE_LIMIT;
  923.   else
  924.     if (z < -COORDINATE_LIMIT)
  925.       z = -COORDINATE_LIMIT;
  926.  
  927.   switch (Pigment->Type) 
  928.   {
  929.   case NO_PIGMENT:
  930.     /* No colouring pigment has been specified - make it black. */
  931.     Make_Colour (Colour, 0.0, 0.0, 0.0);
  932.     Colour -> Filter  = 0.0;
  933.     break;
  934.  
  935.   case COLOUR_PIGMENT:
  936.     Colour -> Red += Pigment->Colour1->Red;
  937.     Colour -> Green += Pigment->Colour1->Green;
  938.     Colour -> Blue += Pigment->Colour1->Blue;
  939.     Colour -> Filter += Pigment->Colour1->Filter;
  940.     break;
  941.  
  942.   case BOZO_PIGMENT:
  943.     bozo (x, y, z, Pigment, Colour);
  944.     break;
  945.  
  946.   case MARBLE_PIGMENT:
  947.     marble (x, y, z, Pigment, Colour);
  948.     break;
  949.  
  950.   case WOOD_PIGMENT:
  951.     wood (x, y, z, Pigment, Colour);
  952.     break;
  953.  
  954.   case CHECKER_PIGMENT:
  955.     checker (x, y, z, Pigment, Colour);
  956.     break;
  957.  
  958.   case SPOTTED_PIGMENT:
  959.     spotted (x, y, z, Pigment, Colour);
  960.     break;
  961.  
  962.   case AGATE_PIGMENT:
  963.     agate (x, y, z, Pigment, Colour);
  964.     break;
  965.  
  966.   case GRANITE_PIGMENT:
  967.     granite (x, y, z, Pigment, Colour);
  968.     break;
  969.  
  970.   case GRADIENT_PIGMENT:
  971.     gradient (x, y, z, Pigment, Colour);
  972.     break;
  973.  
  974.   case HEXAGON_PIGMENT:
  975.     hexagon (x, y, z, Pigment, Colour);
  976.     break;
  977.  
  978.   case RADIAL_PIGMENT:
  979.     radial (x, y, z, Pigment, Colour);
  980.     break;
  981.  
  982.   case MANDEL_PIGMENT:
  983.     mandel (x, y, z, Pigment, Colour);
  984.     break;
  985.  
  986.   case IMAGE_MAP_PIGMENT:
  987.     image_map (x, y, z, Pigment, Colour);
  988.     break;
  989.  
  990.   case ONION_PIGMENT:
  991.     onion (x, y, z, Pigment, Colour);
  992.     break;
  993.  
  994.   case LEOPARD_PIGMENT:
  995.     leopard (x, y, z, Pigment, Colour);
  996.     break;
  997.  
  998.   case PAINTED1_PIGMENT:
  999.     painted1 (x, y, z, Pigment, Colour);
  1000.     break;
  1001.  
  1002.   case PAINTED2_PIGMENT:
  1003.     painted2 (x, y, z, Pigment, Colour);
  1004.     break;
  1005.  
  1006.   case PAINTED3_PIGMENT:
  1007.     painted3 (x, y, z, Pigment, Colour);
  1008.     break;
  1009.   }
  1010.   }
  1011.  
  1012.  
  1013. void Perturb_Normal(Layer_Normal, Tnormal, IPoint)
  1014. VECTOR *Layer_Normal, *IPoint;
  1015. TNORMAL *Tnormal;
  1016.   {
  1017.   register DBL x, y, z;
  1018.   VECTOR TPoint,NTurbulence;
  1019.  
  1020.   if (Tnormal->Trans != NULL) 
  1021.     MInvTransPoint (&TPoint, IPoint, Tnormal->Trans);
  1022.   else 
  1023.     TPoint = *IPoint;
  1024.  
  1025.   x = TPoint.x;
  1026.   y = TPoint.y;
  1027.   z = TPoint.z;
  1028.  
  1029.   if(Tnormal->Flags & HAS_TURB)
  1030.     {
  1031.     DTurbulence (&NTurbulence, x, y, z,
  1032.       Tnormal->omega,Tnormal->lambda,Tnormal->Octaves);
  1033.     x += NTurbulence.x * Tnormal->Turbulence.x;
  1034.     y += NTurbulence.y * Tnormal->Turbulence.y;
  1035.     z += NTurbulence.z * Tnormal->Turbulence.z;
  1036.     }
  1037.  
  1038.  
  1039.   switch (Tnormal->Type) 
  1040.   {
  1041.  
  1042.   case WAVES: 
  1043.     waves (x, y, z, Tnormal, Layer_Normal);
  1044.     break;
  1045.  
  1046.   case RIPPLES: 
  1047.     ripples (x, y, z, Tnormal, Layer_Normal);
  1048.     break;
  1049.  
  1050.   case WRINKLES: 
  1051.     wrinkles (x, y, z, Tnormal, Layer_Normal);
  1052.     break;
  1053.  
  1054.   case BUMPS: 
  1055.     bumps (x, y, z, Tnormal, Layer_Normal);
  1056.     break;
  1057.  
  1058.   case DENTS: 
  1059.     dents (x, y, z, Tnormal, Layer_Normal);
  1060.     break; 
  1061.  
  1062.   case BUMPY1: 
  1063.     bumpy1 (x, y, z, Tnormal, Layer_Normal);
  1064.     break;
  1065.  
  1066.   case BUMPY2: 
  1067.     bumpy2 (x, y, z, Tnormal, Layer_Normal);
  1068.     break;
  1069.  
  1070.   case BUMPY3: 
  1071.     bumpy3 (x, y, z, Tnormal, Layer_Normal);
  1072.     break;
  1073.  
  1074.   case BUMP_MAP: 
  1075.     bump_map (x, y, z, Tnormal, Layer_Normal);
  1076.     break;
  1077.   }
  1078.   return;
  1079.   }
  1080.  
  1081. void Diffuse (Finish, IPoint, Eye, Layer_Normal, Layer_Pigment_Colour, Colour, Attenuation, Object)
  1082. FINISH *Finish;
  1083. VECTOR *IPoint, *Layer_Normal;
  1084. COLOUR *Layer_Pigment_Colour;
  1085. COLOUR *Colour;
  1086. RAY    *Eye;
  1087. DBL    Attenuation;
  1088. OBJECT *Object;
  1089.   {
  1090.   DBL Light_Source_Depth, Cos_Shadow_Angle;
  1091.   RAY Light_Source_Ray;
  1092.   LIGHT_SOURCE *Light_Source;
  1093.   VECTOR REye;
  1094.   COLOUR Light_Colour;
  1095.  
  1096.   if ((Finish->Diffuse == 0.0) && (Finish->Specular == 0.0) && (Finish->Phong == 0.0))
  1097.     return;
  1098.  
  1099.   if (Finish->Specular != 0.0)
  1100.     {
  1101.     REye.x = -Eye->Direction.x;
  1102.     REye.y = -Eye->Direction.y;
  1103.     REye.z = -Eye->Direction.z;
  1104.     }
  1105.  
  1106.   for (Light_Source = Frame.Light_Sources ; 
  1107.   Light_Source != NULL;
  1108.   Light_Source = Light_Source->Next_Light_Source)
  1109.     {
  1110.     /* Get a colour and a ray */
  1111.  
  1112.     do_light(Light_Source,       &Light_Source_Depth, 
  1113.       &Light_Source_Ray,  IPoint,
  1114.       &Light_Colour);
  1115.  
  1116.     /* Don't calculate spotlights when outside of the light's cone */
  1117.     if (fabs(Light_Colour.Red) < BLACK_LEVEL && 
  1118.       fabs(Light_Colour.Green) < BLACK_LEVEL && 
  1119.       fabs(Light_Colour.Blue) < BLACK_LEVEL)
  1120.       continue;
  1121.  
  1122.     /* See if light on far side of surface from camera. */
  1123.  
  1124.     if (!(Object->Type & DOUBLE_ILLUMINATE))
  1125.       {
  1126.        VDot(Cos_Shadow_Angle,*Layer_Normal,Light_Source_Ray.Direction);
  1127.        if (Cos_Shadow_Angle < 0.0)
  1128.          continue;
  1129.       }
  1130.  
  1131.     /* If light source was not blocked by any intervening object, then
  1132.       calculate it's contribution to the object's overall illumination */
  1133.  
  1134.     Shadow_Test_Flag = TRUE;
  1135.     if (Quality_Flags & Q_SHADOW)
  1136.       {
  1137.       if ((Light_Source->Area_Light) && (Quality_Flags & Q_AREA_LIGHT))
  1138.         Block_Area_Light (Light_Source, Light_Source_Depth,
  1139.           &Light_Source_Ray, IPoint,
  1140.           &Light_Colour, 0, 0, 0, 0, 0);
  1141.       else
  1142. #ifdef DB_CODE
  1143.     /* Changes necessary for the light buffer. */
  1144.     if (Extended_Options & USE_LIGHT_BUFFER)
  1145.           Block_Point_Light_Light_Buffer (Light_Source, Light_Source_Depth, &Light_Source_Ray, &Light_Colour);
  1146.         else
  1147.           Block_Point_Light (Light_Source, Light_Source_Depth, &Light_Source_Ray, &Light_Colour);
  1148. #else
  1149.         Block_Point_Light (Light_Source, Light_Source_Depth, &Light_Source_Ray, &Light_Colour);
  1150. #endif
  1151.       }
  1152.     Shadow_Test_Flag = FALSE;
  1153.  
  1154.     if (fabs(Light_Colour.Red)  > BLACK_LEVEL || 
  1155.       fabs(Light_Colour.Green) > BLACK_LEVEL || 
  1156.       fabs(Light_Colour.Blue) > BLACK_LEVEL) 
  1157.       {
  1158.       if (Finish->Phong > 0.0) 
  1159.         do_phong(Finish,&Light_Source_Ray,&Eye->Direction,Layer_Normal,Colour,&Light_Colour, Layer_Pigment_Colour);
  1160.  
  1161.       if (Finish->Specular > 0.0) 
  1162.         do_specular(Finish,&Light_Source_Ray,&REye,Layer_Normal,Colour,&Light_Colour, Layer_Pigment_Colour);
  1163.  
  1164.       if (Finish->Diffuse > 0.0)
  1165.     do_diffuse(Finish,&Light_Source_Ray,Layer_Normal,Colour,&Light_Colour,Layer_Pigment_Colour, Attenuation);
  1166.       }
  1167.     }
  1168.   return;
  1169.   }
  1170.  
  1171. #ifdef DB_CODE
  1172. /* Some things have been optimized. */
  1173. /******************************************************************************
  1174.    The test (Normal_Component < 0.0) is unnecessary!
  1175.  ******************************************************************************/
  1176. void Reflect (Reflection, IPoint, Ray, Layer_Normal, Colour)
  1177. DBL Reflection;
  1178. VECTOR *IPoint;
  1179. RAY *Ray;
  1180. VECTOR *Layer_Normal;
  1181. COLOUR *Colour;
  1182. {
  1183.   RAY New_Ray;
  1184.   COLOUR Temp_Colour;
  1185.   register DBL k; /* Normal_Component */
  1186.  
  1187.   if (Reflection != 0.0)
  1188.   {
  1189.     Reflected_Rays_Traced++;
  1190.     k = 2.0 * (Ray->Direction.x * Layer_Normal->x +
  1191.            Ray->Direction.y * Layer_Normal->y +
  1192.            Ray->Direction.z * Layer_Normal->z);
  1193.  
  1194.     New_Ray.Direction.x = Ray->Direction.x - k * Layer_Normal->x;
  1195.     New_Ray.Direction.y = Ray->Direction.y - k * Layer_Normal->y;
  1196.     New_Ray.Direction.z = Ray->Direction.z - k * Layer_Normal->z;
  1197.  
  1198.     /* ARE 08/25/91 */
  1199.  
  1200.     k = 2.0 * Small_Tolerance;
  1201.  
  1202.     New_Ray.Initial.x = IPoint->x + k * New_Ray.Direction.x;
  1203.     New_Ray.Initial.y = IPoint->y + k * New_Ray.Direction.y;
  1204.     New_Ray.Initial.z = IPoint->z + k * New_Ray.Direction.z;
  1205.  
  1206.     Copy_Ray_Containers (&New_Ray, Ray);
  1207.     Trace_Level++;
  1208.     Make_Colour (&Temp_Colour, 0.0, 0.0, 0.0);
  1209.     New_Ray.Quadric_Constants_Cached = FALSE;
  1210.     Trace (&New_Ray, &Temp_Colour);
  1211.     Trace_Level--;
  1212.  
  1213.     Colour->Red   += Temp_Colour.Red   * Reflection;
  1214.     Colour->Green += Temp_Colour.Green * Reflection;
  1215.     Colour->Blue  += Temp_Colour.Blue  * Reflection;
  1216.   }
  1217. }
  1218. #else
  1219. void Reflect (Reflection, IPoint, Ray, Layer_Normal, Colour)
  1220. DBL Reflection;
  1221. VECTOR *IPoint;
  1222. RAY *Ray;
  1223. VECTOR *Layer_Normal;
  1224. COLOUR *Colour;
  1225.   {
  1226.   RAY New_Ray;
  1227.   COLOUR Temp_Colour;
  1228.   VECTOR Local_Normal;
  1229.   VECTOR Normal_Projection;
  1230.   VECTOR Surface_Offset;
  1231.   register DBL Normal_Component;
  1232.  
  1233.   if (Reflection != 0.0)
  1234.     {
  1235.     Reflected_Rays_Traced++;
  1236.     VDot (Normal_Component, Ray -> Direction, *Layer_Normal);
  1237.     if (Normal_Component < 0.0) 
  1238.       {
  1239.       Local_Normal = *Layer_Normal;
  1240.       Normal_Component *= -1.0;
  1241.       }
  1242.     else
  1243.       VScale (Local_Normal, *Layer_Normal, -1.0);
  1244.  
  1245.     VScale (Normal_Projection, Local_Normal, Normal_Component);
  1246.     VScale (Normal_Projection, Normal_Projection, 2.0);
  1247.     VAdd (New_Ray.Direction, Ray -> Direction, Normal_Projection);
  1248.     New_Ray.Initial = *IPoint;
  1249.  
  1250.     /* ARE 08/25/91 */
  1251.  
  1252.     VScale(Surface_Offset, New_Ray.Direction, 2.0 * Small_Tolerance); 
  1253.     VAdd(New_Ray.Initial, New_Ray.Initial, Surface_Offset);           
  1254.  
  1255.     Copy_Ray_Containers (&New_Ray, Ray);
  1256.     Trace_Level++;
  1257.     Make_Colour (&Temp_Colour, 0.0, 0.0, 0.0);
  1258.     New_Ray.Quadric_Constants_Cached = FALSE;
  1259.     Trace (&New_Ray, &Temp_Colour);
  1260.     Trace_Level--;
  1261.  
  1262.     Colour -> Red   += Temp_Colour.Red   * Reflection;
  1263.     Colour -> Green += Temp_Colour.Green * Reflection;
  1264.     Colour -> Blue  += Temp_Colour.Blue  * Reflection;
  1265.  
  1266.     }
  1267.   }
  1268. #endif
  1269.  
  1270. #ifdef DB_CODE
  1271. /* Some things have been optimized. */
  1272. /******************************************************************************
  1273.    Calculating the refracted ray using Heckbert's method guarantees  
  1274.    that it will be unit!!! (no need to normalize it)                 
  1275.  ******************************************************************************/
  1276. void Refract (Texture, IPoint, Ray, Top_Normal, Colour)
  1277. TEXTURE *Texture;
  1278. VECTOR *IPoint;
  1279. RAY *Ray;
  1280. VECTOR *Top_Normal;
  1281. COLOUR *Colour;
  1282. {
  1283.   RAY New_Ray;
  1284.   COLOUR Temp_Colour;
  1285.   VECTOR Local_Normal;
  1286.   register DBL Normal_Component, Temp_IOR;
  1287.   DBL temp, ior;
  1288.   /*   int inside; */
  1289.  
  1290.   if (Top_Normal == NULL)
  1291.   {
  1292.     New_Ray.Initial = *IPoint;
  1293.     New_Ray.Direction = Ray->Direction;
  1294.  
  1295.     Copy_Ray_Containers (&New_Ray, Ray);
  1296.     Trace_Level++;
  1297.     Transmitted_Rays_Traced++;
  1298.     Make_Colour (&Temp_Colour, 0.0, 0.0, 0.0);
  1299.     New_Ray.Quadric_Constants_Cached = FALSE;
  1300.     Trace (&New_Ray, &Temp_Colour);
  1301.     Trace_Level--;
  1302.     Colour->Red   += Temp_Colour.Red;
  1303.     Colour->Green += Temp_Colour.Green;
  1304.     Colour->Blue  += Temp_Colour.Blue;
  1305.   }
  1306.   else
  1307.   {
  1308.     Refracted_Rays_Traced++;
  1309.     Normal_Component = Ray->Direction.x * Top_Normal->x +
  1310.                Ray->Direction.y * Top_Normal->y +
  1311.                Ray->Direction.z * Top_Normal->z;
  1312.  
  1313.     if (Normal_Component < 0.0)
  1314.     {
  1315.       Local_Normal = *Top_Normal;
  1316.       Normal_Component = -Normal_Component;
  1317.     }
  1318.     else
  1319.     {
  1320.       Local_Normal.x = -Top_Normal->x;
  1321.       Local_Normal.y = -Top_Normal->y;
  1322.       Local_Normal.z = -Top_Normal->z;
  1323.     }
  1324.  
  1325.     Copy_Ray_Containers (&New_Ray, Ray);
  1326.  
  1327.     if (Ray->Containing_Index == -1)
  1328.     {
  1329.       /* The ray is entering from the atmosphere */
  1330.       Ray_Enter (&New_Ray, Texture);
  1331.       ior = (Frame.Atmosphere_IOR)/(Texture->Finish->Index_Of_Refraction);
  1332.     }
  1333.     else
  1334.     {
  1335.       /* The ray is currently inside an object */
  1336.       if (New_Ray.Containing_Textures[New_Ray.Containing_Index] == Texture)
  1337.       {
  1338.     /* The ray is leaving the current object */
  1339.     Ray_Exit (&New_Ray);
  1340.     if (New_Ray.Containing_Index == -1)
  1341.       /* The ray is leaving into the atmosphere */
  1342.       Temp_IOR = Frame.Atmosphere_IOR;
  1343.     else
  1344.       /* The ray is leaving into another object */
  1345.       Temp_IOR = New_Ray.Containing_IORs[New_Ray.Containing_Index];
  1346.  
  1347.     ior = (Texture->Finish->Index_Of_Refraction)/Temp_IOR;
  1348.       }
  1349.       else
  1350.       {
  1351.     /* The ray is entering a new object */
  1352.     Temp_IOR = New_Ray.Containing_IORs[New_Ray.Containing_Index];
  1353.     Ray_Enter (&New_Ray, Texture);
  1354.  
  1355.     ior =  Temp_IOR / (Texture->Finish->Index_Of_Refraction);
  1356.       }
  1357.     }
  1358.  
  1359.     temp = 1.0 + ior * ior * (Normal_Component * Normal_Component - 1.0);
  1360.     if (temp < 0.0)
  1361.     {
  1362.       /* total internal reflection */
  1363.       Reflect ((1.0 - Texture->Finish->Reflection), IPoint,
  1364.     Ray, Top_Normal, Colour);
  1365.       return;
  1366.     }
  1367.  
  1368.     temp = ior*Normal_Component - sqrt(temp);
  1369.     New_Ray.Direction.x = ior * Ray->Direction.x + temp * Local_Normal.x;
  1370.     New_Ray.Direction.y = ior * Ray->Direction.y + temp * Local_Normal.y;
  1371.     New_Ray.Direction.z = ior * Ray->Direction.z + temp * Local_Normal.z;
  1372.  
  1373.     New_Ray.Initial = *IPoint;
  1374.     Trace_Level++;
  1375.     Make_Colour (&Temp_Colour, 0.0, 0.0, 0.0);
  1376.     New_Ray.Quadric_Constants_Cached = FALSE;
  1377.  
  1378.     Trace (&New_Ray, &Temp_Colour);
  1379.     Trace_Level--;
  1380.  
  1381.     Colour->Red   += Temp_Colour.Red * Texture->Finish->Refraction;
  1382.     Colour->Green += Temp_Colour.Green * Texture->Finish->Refraction;
  1383.     Colour->Blue  += Temp_Colour.Blue * Texture->Finish->Refraction;
  1384.   }
  1385. }
  1386. #else
  1387. void Refract (Texture, IPoint, Ray, Top_Normal, Colour)
  1388. TEXTURE *Texture;
  1389. VECTOR *IPoint;
  1390. RAY *Ray;
  1391. VECTOR *Top_Normal;
  1392. COLOUR *Colour;
  1393.   {
  1394.   RAY New_Ray;
  1395.   COLOUR Temp_Colour;
  1396.   VECTOR Local_Normal;
  1397.   VECTOR Ray_Direction;
  1398.   register DBL Normal_Component, Temp_IOR;
  1399.   DBL temp, ior;
  1400.   /*   int inside; */
  1401.  
  1402.   if (Top_Normal == NULL)
  1403.     {
  1404.     New_Ray.Initial = *IPoint;
  1405.     New_Ray.Direction = Ray->Direction;
  1406.  
  1407.     Copy_Ray_Containers (&New_Ray, Ray);
  1408.     Trace_Level++;
  1409.     Transmitted_Rays_Traced++;
  1410.     Make_Colour (&Temp_Colour, 0.0, 0.0, 0.0);
  1411.     New_Ray.Quadric_Constants_Cached = FALSE;
  1412.     Trace (&New_Ray, &Temp_Colour);
  1413.     Trace_Level--;
  1414.     (Colour -> Red) += Temp_Colour.Red;
  1415.     (Colour -> Green) += Temp_Colour.Green;
  1416.     (Colour -> Blue) += Temp_Colour.Blue;
  1417.     }
  1418.   else
  1419.     {
  1420.     Refracted_Rays_Traced++;
  1421.     VDot (Normal_Component, Ray -> Direction, *Top_Normal);
  1422.     if (Normal_Component <= 0.0)
  1423.       {
  1424.       Local_Normal.x = Top_Normal -> x;
  1425.       Local_Normal.y = Top_Normal -> y;
  1426.       Local_Normal.z = Top_Normal -> z;
  1427.       Normal_Component *= -1.0;
  1428.       /*     inside = FALSE;*/
  1429.       }
  1430.     else
  1431.       {
  1432.       VScale (Local_Normal, *Top_Normal, -1.0);
  1433.       /*     inside = TRUE;*/
  1434.       }
  1435.  
  1436.  
  1437.     Copy_Ray_Containers (&New_Ray, Ray);
  1438.  
  1439.     if (Ray -> Containing_Index == -1)
  1440.       {
  1441.       /* The ray is entering from the atmosphere */
  1442.       Ray_Enter (&New_Ray, Texture);
  1443.       ior = (Frame.Atmosphere_IOR)/(Texture->Finish->Index_Of_Refraction);
  1444.       }
  1445. else
  1446.   {
  1447.   /* The ray is currently inside an object */
  1448.   if (New_Ray.Containing_Textures [New_Ray.Containing_Index] == Texture) 
  1449.     /*         if (inside) */
  1450.     {
  1451.     /* The ray is leaving the current object */
  1452.     Ray_Exit (&New_Ray);
  1453.     if (New_Ray.Containing_Index == -1)
  1454.       /* The ray is leaving into the atmosphere */
  1455.     Temp_IOR = Frame.Atmosphere_IOR;
  1456.     else
  1457.       /* The ray is leaving into another object */
  1458.       Temp_IOR = New_Ray.Containing_IORs [New_Ray.Containing_Index];
  1459.  
  1460.     ior =  (Texture->Finish->Index_Of_Refraction)/Temp_IOR;
  1461.     }
  1462.     else
  1463.       {
  1464.       /* The ray is entering a new object */
  1465.       Temp_IOR = New_Ray.Containing_IORs [New_Ray.Containing_Index];
  1466.       Ray_Enter (&New_Ray, Texture);
  1467.  
  1468.       ior =  Temp_IOR / (Texture->Finish->Index_Of_Refraction);
  1469.       }
  1470.     }
  1471.  
  1472.   temp = 1.0 + ior * ior * (Normal_Component * Normal_Component - 1.0);
  1473.   if (temp < 0.0) 
  1474.       {
  1475.     Reflect ((1.0 - Texture->Finish->Reflection), IPoint, 
  1476.     Ray, Top_Normal, Colour);
  1477.     return;
  1478.     }
  1479.  
  1480.   temp = ior*Normal_Component - sqrt(temp);
  1481.   VScale (Local_Normal, Local_Normal, temp);
  1482.   VScale (Ray_Direction, Ray->Direction, ior);
  1483.   VAdd (New_Ray.Direction, Local_Normal, Ray_Direction);
  1484.   VNormalize (New_Ray.Direction, New_Ray.Direction);
  1485.  
  1486.   New_Ray.Initial = *IPoint;
  1487.   Trace_Level++;
  1488.   Make_Colour (&Temp_Colour, 0.0, 0.0, 0.0);
  1489.   New_Ray.Quadric_Constants_Cached = FALSE;
  1490.  
  1491.   Trace (&New_Ray, &Temp_Colour);
  1492.   Trace_Level--;
  1493.  
  1494.   (Colour -> Red) += (Temp_Colour.Red)
  1495.     * (Texture -> Finish->Refraction);
  1496.   (Colour -> Green) += (Temp_Colour.Green)
  1497.     * (Texture -> Finish->Refraction);
  1498.   (Colour -> Blue) += (Temp_Colour.Blue)
  1499.     * (Texture -> Finish->Refraction);
  1500.   }
  1501. }
  1502. #endif
  1503.  
  1504. void Fog (Distance, Fog_Colour, Fog_Distance, Colour)
  1505. DBL Distance, Fog_Distance;
  1506. COLOUR *Fog_Colour, *Colour;
  1507.   {
  1508.   DBL Fog_Factor, Fog_Factor_Inverse;
  1509.  
  1510.   Fog_Factor = exp(-1.0 * Distance/Fog_Distance);
  1511.   Fog_Factor_Inverse = 1.0 - Fog_Factor;
  1512.   Colour->Red = Colour->Red*Fog_Factor + Fog_Colour->Red*Fog_Factor_Inverse;
  1513.   Colour->Green = Colour->Green*Fog_Factor + Fog_Colour->Green*Fog_Factor_Inverse;
  1514.   Colour->Blue = Colour->Blue*Fog_Factor + Fog_Colour->Blue*Fog_Factor_Inverse;
  1515.   }
  1516.  
  1517. void Compute_Reflected_Colour (Ray, Finish, Ray_Intersection, Layer_Pigment_Colour, Filter_Colour, Colour, Layer_Normal)
  1518. RAY *Ray;
  1519. FINISH *Finish;
  1520. INTERSECTION *Ray_Intersection;
  1521. COLOUR *Layer_Pigment_Colour;
  1522. COLOUR *Filter_Colour;
  1523. COLOUR *Colour;
  1524. VECTOR *Layer_Normal;
  1525.   {
  1526.   DBL Attenuation, Ambient;
  1527.   COLOUR Emitted_Colour;
  1528.  
  1529.   /* This variable keeps track of how much colour comes from the surface
  1530.       of the object and how much is transmited through. */
  1531.   Make_Colour (&Emitted_Colour, 0.0, 0.0, 0.0);
  1532.  
  1533.   if (Quality_Flags & Q_FULL_AMBIENT) 
  1534.     {
  1535.     Layer_Pigment_Colour->Filter = 0.0;
  1536.  
  1537.     Colour->Red   += Layer_Pigment_Colour->Red * Filter_Colour->Filter;
  1538.     Colour->Green += Layer_Pigment_Colour->Green * Filter_Colour->Filter;
  1539.     Colour->Blue  += Layer_Pigment_Colour->Blue * Filter_Colour->Filter;
  1540.     return;
  1541.     }
  1542.  
  1543.   Attenuation = Filter_Colour->Filter * (1.0 - Layer_Pigment_Colour->Filter);
  1544.  
  1545.   if ((Ambient = Finish->Ambient*Attenuation) != 0.0)
  1546.     {
  1547.     Emitted_Colour.Red += Layer_Pigment_Colour->Red * Ambient;
  1548.     Emitted_Colour.Green += Layer_Pigment_Colour->Green * Ambient;
  1549.     Emitted_Colour.Blue += Layer_Pigment_Colour->Blue * Ambient;
  1550.     }
  1551.  
  1552.   Diffuse (Finish, &Ray_Intersection->IPoint, Ray,
  1553.     Layer_Normal, Layer_Pigment_Colour, &Emitted_Colour, Attenuation, 
  1554.     Ray_Intersection->Object);
  1555.  
  1556.   Colour->Red   += Emitted_Colour.Red;
  1557.   Colour->Green += Emitted_Colour.Green;
  1558.   Colour->Blue  += Emitted_Colour.Blue;
  1559.  
  1560.   if (Quality_Flags & Q_REFLECT)
  1561.     Reflect (Finish->Reflection, &Ray_Intersection -> IPoint, Ray,
  1562.       Layer_Normal, Colour);
  1563.   }
  1564.  
  1565. /* Given an intersection point, a ray, & a shadow flag, add that point's
  1566.   color to the given colour and return it. */
  1567.  
  1568. void Determine_Apparent_Colour (Ray_Intersection, Colour, Ray)
  1569. INTERSECTION *Ray_Intersection;
  1570. COLOUR *Colour;
  1571. RAY *Ray;
  1572.   {
  1573.   COLOUR Layer_Pigment_Colour, Refracted_Colour, Filter_Colour;
  1574.   TEXTURE *Layer, *Texture;
  1575.   FINISH *Finish;
  1576.   VECTOR Layer_Normal, Raw_Normal, Top_Normal;
  1577.   DBL Normal_Direction;
  1578.   int layer_number;
  1579.  
  1580. #define QColour Texture->Pigment->Quick_Colour
  1581.  
  1582.   /* Get the normal to the surface */
  1583.   if (Ray_Intersection->NFlag)
  1584.      Raw_Normal = Ray_Intersection->INormal;
  1585.   else
  1586.      Normal (&Raw_Normal, Ray_Intersection->Object, &Ray_Intersection->IPoint);
  1587.  
  1588.   /* Now, we perform the lighting calculations. */
  1589.  
  1590.   /* We assume here that Post_Process has propagated all parent
  1591.    textures to the object itself and that everything has some texture.
  1592.    Redirrect to the proper texture if its a material or checker texture */
  1593.  
  1594.   for (Texture = Ray_Intersection->Object->Texture;
  1595.   Texture->Type != PNF_TEXTURE;)
  1596.     switch (Texture->Type)
  1597.     {
  1598.     case TILE_TEXTURE:
  1599.       Texture = tiles_texture(&Ray_Intersection->IPoint,((TILES *)Texture));
  1600.       break;
  1601.     case MAT_TEXTURE:
  1602.       Texture = material_map(&Ray_Intersection->IPoint,((MATERIAL *)Texture));
  1603.       break;
  1604.     default:
  1605.       fprintf(stderr, "Bad texture type: %d\n", Texture->Type);
  1606.       close_all(); 
  1607.       exit(1);
  1608.     };
  1609.  
  1610.   Make_ColourA (&Filter_Colour, 1.0, 1.0, 1.0, 1.0);
  1611.   for (layer_number=1 , Layer = Texture;
  1612.   (Layer != NULL) && (fabs(Filter_Colour.Filter) > BLACK_LEVEL);
  1613.   layer_number++, Layer = Layer->Next_Layer)
  1614.     {
  1615.     Make_Colour (&Layer_Pigment_Colour, 0.0, 0.0, 0.0);
  1616.     if (Quality_Flags & Q_QUICKC)
  1617.       Layer_Pigment_Colour = QColour;
  1618.     else
  1619.       Add_Pigment (&Layer_Pigment_Colour, Layer->Pigment, &Ray_Intersection->IPoint);
  1620.  
  1621.     Layer_Normal = Raw_Normal;
  1622.     if ((Quality_Flags & Q_NORMAL) && (Texture->Tnormal != NULL))
  1623.       Perturb_Normal (&Layer_Normal, Texture->Tnormal,
  1624.         &Ray_Intersection->IPoint);
  1625.  
  1626.     /* If the surface normal points away, flip its direction. */
  1627.     VDot (Normal_Direction, Layer_Normal, Ray->Direction);
  1628.     if (Normal_Direction > 0.0) 
  1629.       {
  1630. #ifdef DB_CODE
  1631.       /* Some things have been optimized. */
  1632.       Layer_Normal.x = -Layer_Normal.x;
  1633.       Layer_Normal.y = -Layer_Normal.y;
  1634.       Layer_Normal.z = -Layer_Normal.z;
  1635. #else
  1636.       VScaleEq (Layer_Normal, -1.0);
  1637. #endif
  1638.       }
  1639.     if (layer_number == 1)
  1640.       Top_Normal = Layer_Normal;
  1641.  
  1642.     Compute_Reflected_Colour (Ray,
  1643.       Layer->Finish,
  1644.       Ray_Intersection,
  1645.       &Layer_Pigment_Colour,
  1646.       &Filter_Colour,
  1647.       Colour, &Layer_Normal);
  1648.  
  1649.     Filter_Colour.Red   *= Layer_Pigment_Colour.Red;
  1650.     Filter_Colour.Green *= Layer_Pigment_Colour.Green;
  1651.     Filter_Colour.Blue  *= Layer_Pigment_Colour.Blue;
  1652.     Filter_Colour.Filter *= Layer_Pigment_Colour.Filter;
  1653.     }
  1654.  
  1655.   Finish = Texture->Finish;
  1656.  
  1657.   if ((fabs(Filter_Colour.Filter) > BLACK_LEVEL) && (Quality_Flags & Q_REFRACT))
  1658.     {
  1659.     Make_Colour (&Refracted_Colour, 0.0, 0.0, 0.0);
  1660.  
  1661.     if (Finish->Refraction > 0.0)
  1662.       Refract (Texture, &Ray_Intersection -> IPoint, Ray,
  1663.     &Top_Normal, &Refracted_Colour);
  1664.     else
  1665.       Refract (Texture, &Ray_Intersection->IPoint, Ray,
  1666.     NULL, &Refracted_Colour);
  1667.  
  1668.     Colour->Red += Filter_Colour.Red * Refracted_Colour.Red * Filter_Colour.Filter;
  1669.     Colour->Green += Filter_Colour.Green * Refracted_Colour.Green * Filter_Colour.Filter;
  1670.     Colour->Blue += Filter_Colour.Blue * Refracted_Colour.Blue * Filter_Colour.Filter;
  1671.     }
  1672.  
  1673.   if (Frame.Fog_Distance != 0.0)
  1674.     Fog (Ray_Intersection->Depth, &Frame.Fog_Colour, Frame.Fog_Distance,
  1675.       Colour);
  1676.   }
  1677.  
  1678. void Filter_Shadow_Ray (Ray_Intersection, Colour)
  1679. INTERSECTION *Ray_Intersection;
  1680. COLOUR *Colour;
  1681.   {
  1682.   COLOUR Layer_Pigment_Colour, Filter_Colour;
  1683.   TEXTURE *Layer, *Texture;
  1684.   FINISH *Finish;
  1685.   int layer_number;
  1686.  
  1687. #define QColour Texture->Pigment->Quick_Colour
  1688.  
  1689.   if (!(Quality_Flags & Q_SHADOW))
  1690.     return;
  1691.  
  1692.   /* Now, we perform the lighting calculations. */
  1693.  
  1694.   /* We assume here that Post_Process has propagated all parent
  1695.    textures to the object itself and that everything has some texture.
  1696.    Redirrect to the proper texture if its a material or checker texture */
  1697.  
  1698.   for (Texture = Ray_Intersection->Object->Texture;
  1699.   Texture->Type != PNF_TEXTURE;)
  1700.     switch (Texture->Type)
  1701.     {
  1702.     case TILE_TEXTURE:
  1703.       Texture = tiles_texture(&Ray_Intersection->IPoint,((TILES *)Texture));
  1704.       break;
  1705.     case MAT_TEXTURE:
  1706.       Texture = material_map(&Ray_Intersection->IPoint,((MATERIAL *)Texture));
  1707.       break;
  1708.     default:
  1709.       fprintf(stderr, "Bad texture type: %d\n", Texture->Type);
  1710.       close_all(); 
  1711.       exit(1);
  1712.     };
  1713.  
  1714.   Make_ColourA (&Filter_Colour, 1.0, 1.0, 1.0, 1.0);
  1715.   for (layer_number=1 , Layer = Texture;
  1716.   (Layer != NULL) && (fabs(Filter_Colour.Filter) > BLACK_LEVEL);
  1717.   layer_number++, Layer = Layer->Next_Layer)
  1718.     {
  1719.     if (Quality_Flags & Q_QUICKC)
  1720.       Layer_Pigment_Colour = QColour;
  1721.     else
  1722.       {
  1723.       Make_Colour (&Layer_Pigment_Colour, 0.0, 0.0, 0.0);
  1724.       Add_Pigment (&Layer_Pigment_Colour, Layer->Pigment, &Ray_Intersection->IPoint);
  1725.       }
  1726.  
  1727.     Filter_Colour.Red   *= Layer_Pigment_Colour.Red;
  1728.     Filter_Colour.Green *= Layer_Pigment_Colour.Green;
  1729.     Filter_Colour.Blue  *= Layer_Pigment_Colour.Blue;
  1730.     Filter_Colour.Filter *= Layer_Pigment_Colour.Filter;
  1731.     }
  1732.  
  1733.   Finish = Texture->Finish;
  1734.  
  1735.   /* For shadow rays, we have the filter colour now - time to return */
  1736.   if (fabs(Filter_Colour.Filter) < BLACK_LEVEL) 
  1737.     {
  1738.     Make_Colour (Colour, 0.0, 0.0, 0.0);
  1739.     return;
  1740.     }
  1741.  
  1742.   if (Finish->Refraction > 0.0) 
  1743.     {
  1744.     Colour->Red *= Filter_Colour.Red * Finish->Refraction * Filter_Colour.Filter;
  1745.     Colour->Green *= Filter_Colour.Green * Finish->Refraction * Filter_Colour.Filter;
  1746.     Colour->Blue *= Filter_Colour.Blue * Finish->Refraction * Filter_Colour.Filter;
  1747.     }
  1748.   else 
  1749.     {
  1750.     Colour->Red *= Filter_Colour.Red * Filter_Colour.Filter;
  1751.     Colour->Green *= Filter_Colour.Green * Filter_Colour.Filter;
  1752.     Colour->Blue *= Filter_Colour.Blue * Filter_Colour.Filter;
  1753.     }
  1754.   return;
  1755.  
  1756.   }
  1757.